// 实现语音识别子服务
#include <brpc/server.h>
#include <butil/logging.h>

#include "asr.hpp"     // 语音识别模块封装
#include "etcd.hpp"    // 服务注册模块封装
#include "logger.hpp"  // 日志模块封装
#include "speech.pb.h" // protobuf 框架代码

namespace bite_im
{
    // 语音识别服务对象
    class SpeechServiceImpl : public bite_im::SpeechService
    {
    public:
        SpeechServiceImpl(const ASRClient::ptr &asr_client) 
            : _asr_client(asr_client)
        {}

        ~SpeechServiceImpl() {}

        virtual void SpeechRecognition(google::protobuf::RpcController *controller, const bite_im::SpeechRecognitionReq *request,
            bite_im::SpeechRecognitionRsp *response, google::protobuf::Closure *done) override
        {   // done 通常用于通知框架 RPC 调用已完成，框架会负责清理资源并返回响应给客户端
            brpc::ClosureGuard rpc_guard(done); // done->run();
            // 1. 取出请求中的语音数据
            // 2. 调用语音 sdk 模块进行语音识别，得到响应 
            std::string err;
            std::string res = _asr_client->recognize(request->speech_content(), err);
            if (res.empty()) {
                LOG_ERROR("{} 语音识别失败！", request->request_id());
                response->set_request_id(request->request_id());
                response->set_success(false);
                response->set_errmsg("语音识别失败: " + err);
                return ;
            }
            // 3. 组织响应
            response->set_request_id(request->request_id());
            response->set_success(true);
            response->set_recognition_result(res);
        }
    private:
        ASRClient::ptr _asr_client;
    };

    class SpeechServer {
    public:
        using ptr = std::shared_ptr<SpeechServer>;
        SpeechServer(const ASRClient::ptr &asr_client, const Registry::ptr &reg_client, const std::shared_ptr<brpc::Server> &rpc_server) 
            : _asr_client(asr_client),
            _reg_client(reg_client),
            _rpc_server(rpc_server)
        {}

        ~SpeechServer() {}

        // 用于搭建 RPC 服务器，并启动服务器
        void start() {
            _rpc_server->RunUntilAskedToQuit();
        }
    private:
        ASRClient::ptr _asr_client;
        Registry::ptr _reg_client;      // 服务注册客户端
        std::shared_ptr<brpc::Server> _rpc_server;
    };

    // 建造者模式
    class SpeechServerBuilder {
    public:
        // 构造语音识别客户端对象
        void make_asr_object(const std::string &appid, const std::string &api_key, const std::string &secret_key) {
            _asr_client = std::make_shared<ASRClient>(appid, api_key, secret_key);
        }

        // 构造服务注册客户端对象  注册中心地址   服务名称  服务地址
        void make_reg_object(const std::string &reg_host, const std::string &service_name, const std::string &access_host) {
            _reg_client = std::make_shared<Registry>(reg_host);
            _reg_client->registry(service_name, access_host);
        }

        // 构造RPC服务器对象
        void make_rpc_server(uint16_t port, uint32_t timeout, uint8_t num_threads) {
            if (!_asr_client) {
                LOG_ERROR("还未初始化语音识别模块！");
                abort();
            }
            _rpc_server = std::make_shared<brpc::Server>();
            // 关闭 brpc 的默认日志输出
            logging::LoggingSettings settings;
            settings.logging_dest = logging::LoggingDestination::LOG_TO_NONE;
            logging::InitLogging(settings);

            SpeechServiceImpl *speech_service = new SpeechServiceImpl(_asr_client);
            int ret = _rpc_server->AddService(speech_service, brpc::ServiceOwnership::SERVER_OWNS_SERVICE); // SERVER_OWNS_SERVICE 添加服务失败时或者服务退出，负责删除服务对象
            if (ret == -1) {
                LOG_ERROR("添加Rpc服务失败！");
                abort();
            }
            brpc::ServerOptions options;
            options.idle_timeout_sec = timeout;             // 连接超时销毁
            options.num_threads = num_threads;              // io线程数
            ret = _rpc_server->Start(port, &options);
            if (ret == -1) {
                LOG_ERROR("启动服务器失败!");
                abort();
            }
        }   

        SpeechServer::ptr build() {
            if (!_asr_client) {
                LOG_ERROR("还未初始化语音识别模块！");
                abort();
            }
            if (!_reg_client) {
                LOG_ERROR("还未初始化服务注册模块！");
                abort();
            }
            if (!_rpc_server) {
                LOG_ERROR("还未初始化RPC服务器模块！");
                abort();
            }   
            SpeechServer::ptr server = std::make_shared<SpeechServer>(_asr_client, _reg_client, _rpc_server);
            return server;
        }

    private:
        ASRClient::ptr _asr_client;
        Registry::ptr _reg_client;      // 服务注册客户端
        std::shared_ptr<brpc::Server> _rpc_server;
    };
}